<?php
namespace Sumpay;
class Sumpay
{
    // 作者
    protected $author;

    /**
     * HelloWorld constructor.
     * @param string $author
     */
    public function __construct($author = 'scort')
    {
        $this->author = $author;
    }

    /**
     * 执行方法
     * @return string
     */
    public function info()
    {
        $info = "Hello World ! \n";
        $info .= "\t--Power By ";
        $info .= $this->author . "\n";
        return $info;
    }



    public static function execute($url, $charset, $data, $privateKeyName, $password, $publicKeyName, $domain, $charset_change_fields, $encrypted_fields, $special_fields, $json_array_fields, $useMultipart, $file_fields, $defaultCharset)


    {
        if (phpversion() >= 7.1) {
            $aes = new NewCryptAES();
            $aesKey = $aes->getAesKey();
            $aes->set_key($aesKey);
        } else {
            $aes = new CryptAES();
            $aesKey = $aes->getAesKey();
            $aes->set_key($aesKey);
            $aes->require_pkcs5();
        }
        $data = self::processJSONArrayFields($data, $charset, $charset_change_fields, $encrypted_fields, $special_fields, $json_array_fields, $defaultCharset, $aes);
        $data = self::charsetChange($charset_change_fields, $data, $charset, $defaultCharset);
        $data = self::encryptByAesKey($encrypted_fields, $data, $aes);
        $aesKey = self::encrpyt(base64_encode($aesKey), $publicKeyName);
        $data['aes_key'] = $aesKey;
        $data = self::specialChange($special_fields, $data);
        $signStr = self::sign(getStr($data), $privateKeyName, $password);
        $data['sign'] = $signStr;
        $data['sign_type'] = 'CERT';

        if ($useMultipart) {
            $optional_headers = array(
                "Referer: " . $domain,
                'Content-type: multipart/form-data'
            );
            return self::do_post_multipart_request($url, $data, $file_fields, $optional_headers);
        } else {
            $optional_headers = array(
                "Referer: " . $domain
            );
            return self::do_post_request($url, $data, $optional_headers);
        }
    }

    public static function processJSONObjectFields($data, $charset, $charset_change_fields, $encrypted_fields, $special_fields, $json_fields, $defaultCharset, $aes)
    {
        foreach ($json_fields as $key) {
            if (isset($data[$key])) {
                $json_obejct = json_decode($data[$key], TRUE);
                $json_obejct = self::charsetChange($charset_change_fields, $json_obejct, $charset, $defaultCharset);
                $json_obejct = self::encryptByAesKey($encrypted_fields, $json_obejct, $aes);
                $json_obejct = self::specialChange($special_fields, $json_obejct);
                $data[$key] = json_encode($json_obejct);
            }
        }
        return $data;
    }

    public static function processJSONArrayFields($data, $charset, $charset_change_fields, $encrypted_fields, $special_fields, $json_array_fields, $defaultCharset, $aes)
    {
        foreach ($json_array_fields as $key) {
            if (isset($data[$key])) {
                $json_array = json_decode($data[$key], TRUE);
                for ($i = 0; $i < count($json_array); $i++) {
                    $json_obejct = $json_array[$i];
                    $json_obejct = self::charsetChange($charset_change_fields, $json_obejct, $charset, $defaultCharset);
                    $json_obejct = self::encryptByAesKey($encrypted_fields, $json_obejct, $aes);
                    $json_obejct = self::specialChange($special_fields, $json_obejct);
                    $json_array[$i] = $json_obejct;
                }
                $data[$key] = json_encode($json_array);
            }
        }
        return $data;
    }

    public static function charsetChange($charset_change_fields, $data, $merCharset, $defaultCharset)
    {
        if ($defaultCharset == $merCharset) {
            return $data;
        }
        foreach ($charset_change_fields as $key) {
            if (isset($data[$key])) {
                $value = $data[$key];
                if ($value && "" != $value) {
                    $data[$key] = iconv($merCharset, $defaultCharset, $value);
                }
            }
        }
        return $data;
    }

    public static function encryptByAesKey($encrypted_fields, $data, $aes)
    {
        foreach ($encrypted_fields as $key) {
            if (isset($data[$key])) {
                $value = $data[$key];
                if ($value && "" != $value) {
                    $data[$key] = $aes->encrypt($value);
                }
            }
        }
        return $data;
    }

    public static function specialChange($special_fields, $data)
    {
        foreach ($special_fields as $key) {
            if (isset($data[$key])) {
                $value = $data[$key];
                if ($value && "" != $value) {
                    $data[$key] = base64_encode($value);
                }
            }
        }
        return $data;
    }


    public static function sign($data, $privateKeyPath, $password)
    {
        $certs = array();
        openssl_pkcs12_read(file_get_contents($privateKeyPath), $certs, $password);
        if (!$certs) {
            return;
        }
        $signature = '';
        openssl_sign($data, $signature, $certs['pkey'], 'sha256');
        return base64_encode($signature);
    }

    public static function verify($data, $signature, $publicKeyName)
    {
        $result = (bool)openssl_verify($data, base64_decode($signature), file_get_contents($publicKeyName), 'sha256');
        return $result;
    }

    public static function encrpyt($data, $publicKeyName)
    {
        openssl_public_encrypt($data, $encrypted, file_get_contents($publicKeyName)); //公钥加密
        return base64_encode($encrypted);
    }

    public static function getStr($parameters)
    {

        $parameters = array_filter($parameters, create_function('$v', 'return $v != \'\' || $v == \'0\';'));
        $needSign = '';
        $first = true;
        ksort($parameters);
        foreach (array_keys($parameters) as $key) {
            if ($first) {
                $first = false;
            } else {
                $needSign .= "&";
            }
            $needSign .= $key;
            $needSign .= "=";
            $needSign .= $parameters[$key];
        }
        return $needSign;
    }
    public static function do_post_request($url, $data, $optional_headers = null)
    {
        $params = array(
            'http' => array(
                'method' => 'POST',
                'content' => http_build_query($data)
            )
        );
        if ($optional_headers !== null) {
            $params['http']['header'] = $optional_headers;
        }
        $ctx = stream_context_create($params);
        $fp = @fopen($url, 'rb', false, $ctx);
        if (!$fp) {
            throw new Exception("Problem with $url, $php_errormsg");
        }
        $response = @stream_get_contents($fp);
        if ($response === false) {
            throw new Exception("Problem reading data from $url, $php_errormsg");
        }

        $obj = json_decode($response, TRUE);
        $signature = $obj['sign'];
        $obj['sign'] = '';
        $obj['sign_type'] = '';
        $data = self::getStr($obj);
        $re = self::verify($data, $signature, '../cer/yixun.cer');
        if ($re) {
            return $obj;
        }
        return json_decode("{'resp_code':'888888','resp_msg':'验签失败'}", TRUE);
    }

    public static function do_post_multipart_request($url, $data, $file_fields = null, $optional_headers = null)
    {
        $cURLHandle = curl_init($url);
        if ($file_fields != null) {
            foreach ($file_fields as $key => $value) {
                $data[$key] = $value;
            }
        }
        curl_setopt($cURLHandle, CURLOPT_POST, true);
        curl_setopt($cURLHandle, CURLOPT_POSTFIELDS, $data);
        //设置头文件的信息作为数据流输出
        //     curl_setopt($cURLHandle, CURLOPT_HEADER, 0);
        //设置获取的信息以文件流的形式返回，而不是直接输出。
        curl_setopt($cURLHandle, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($cURLHandle, CURLOPT_HTTPHEADER, $optional_headers);
        $result = curl_exec($cURLHandle);
        $php_errormsg = null;
        if (curl_errno($cURLHandle)) {
            $php_errormsg = curl_error($cURLHandle);
        }
        curl_close($cURLHandle);
        if ($php_errormsg != null) {
            throw new Exception("Problem reading data from $url, $php_errormsg");
        }

        $obj = json_decode($result, TRUE);
        $signature = $obj['sign'];
        $obj['sign'] = '';
        $obj['sign_type'] = '';
        $data = self::getStr($obj);
        $re = self::verify($data, $signature, '../cer/yixun.cer');
        if ($re) {
            return $obj;
        }
        return json_decode("{'resp_code':'888888','resp_msg':'验签失败'}", TRUE);
    }
}
